#define ARDUINO_USB_MODE 1
#define ARDUINO_USB_CDC_ON_BOOT 1

#include "Adafruit_TinyUSB.h"

// 自定义绝对坐标 HID 报告描述符（16bit X/Y）
uint8_t const desc_hid_report[] = {
  0x05, 0x01,       // Usage Page (Generic Desktop)
  0x09, 0x02,       // Usage (Mouse)
  0xA1, 0x01,       // Collection (Application)
  0x09, 0x01,       //   Usage (Pointer)
  0xA1, 0x00,       //   Collection (Physical)
  0x05, 0x09,       //     Usage Page (Buttons)
  0x19, 0x01,       //     Usage Minimum (1)
  0x29, 0x03,       //     Usage Maximum (3)
  0x15, 0x00,       //     Logical Minimum (0)
  0x25, 0x01,       //     Logical Maximum (1)
  0x95, 0x03,       //     Report Count (3)
  0x75, 0x01,       //     Report Size (1)
  0x81, 0x02,       //     Input (Data, Variable, Absolute) - Buttons
  0x95, 0x01,       //     Report Count (1)
  0x75, 0x05,       //     Report Size (5)
  0x81, 0x03,       //     Input (Constant, Variable, Absolute) - Padding
  0x05, 0x01,       //     Usage Page (Generic Desktop)
  0x09, 0x30,       //     Usage (X)
  0x09, 0x31,       //     Usage (Y)
  0x16, 0x00, 0x00, //     Logical Minimum (0)
  0x26, 0xFF, 0x7F, //     Logical Maximum (32767)
  0x75, 0x10,       //     Report Size (16)
  0x95, 0x02,       //     Report Count (2)
  0x81, 0x02,       //     Input (Data, Variable, Absolute)
  0xC0,             //   End Collection
  0xC0              // End Collection
};

Adafruit_USBD_HID usb_hid;

uint16_t screenWidth = 1920;
uint16_t screenHeight = 1080;
uint16_t centerX = screenWidth / 2;
uint16_t centerY = screenHeight / 2;

// 屏幕宽度和 16bit 坐标系统的最大值对应的比例
float x_scale = 32767.0 / screenWidth;
float y_scale = 32767.0 / screenHeight;

uint32_t lastMoveTime = 0;  // 用于跟踪上次回到中心的时间

void setup() {
  Serial0.begin(115200);
  if (!TinyUSBDevice.isInitialized()) {
    TinyUSBDevice.begin(0);
  }
  usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
  usb_hid.setPollInterval(2);
  usb_hid.setStringDescriptor("Absolute Mouse");
  usb_hid.begin();
  // If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
  if (TinyUSBDevice.mounted()) {
    TinyUSBDevice.detach();
    delay(10);
    TinyUSBDevice.attach();
  }
  delay(2000);  // 等待 USB 枚举
  Serial0.println("Setup done");
}

void loop() {
  // 将屏幕坐标转换为16bit坐标
  int16_t scaledX = centerX * x_scale;
  int16_t scaledY = centerY * y_scale;
  // 只在 USB HID 设备准备好时更新坐标并发送报告
  if (usb_hid.ready() && millis() - lastMoveTime >= 5000) {
    lastMoveTime = millis(); 
    uint8_t report[5];
    report[0] = 0; // 无按钮按下
    report[1] = scaledX & 0xFF;
    report[2] = (scaledX >> 8) & 0xFF;
    report[3] = scaledY & 0xFF;
    report[4] = (scaledY >> 8) & 0xFF;

    usb_hid.sendReport(0, report, sizeof(report));
    Serial0.printf("Moved to: (%d, %d)\n", centerX, centerY);
  }
  delay(1000);  // 延时1秒，以便鼠标位置更新
}
